package com.woniuxy.certified.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.certified.dao.CertifiedAccount;
import com.woniuxy.certified.dao.CertifiedInfo;
import com.woniuxy.certified.mapper.CertifiedAccountMapper;
import com.woniuxy.certified.mapper.CertifiedInfoMapper;
import com.woniuxy.certified.model.dto.CertifiedAccountDto;
import com.woniuxy.certified.model.dto.CertifiedAccountInfoDto;
import com.woniuxy.certified.model.param.*;
import com.woniuxy.certified.service.CertifiedAccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.core.exception.certifiedException.CertifiedException;
import com.woniuxy.core.exception.certifiedException.CertifiedExceptionCode;
import com.woniuxy.core.staticCode.CertifiedCode;
import com.woniuxy.core.util.JwtUtil;
import com.woniuxy.core.util.PageInfo;
import com.woniuxy.core.util.RedisKeyUtil;
import com.woniuxy.core.util.RedisUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.management.Query;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 凌玉春
 * @since 2024年01月15日
 */
@Service
public class CertifiedAccountServiceImpl extends ServiceImpl<CertifiedAccountMapper, CertifiedAccount> implements CertifiedAccountService {

    @Resource
    private CertifiedAccountMapper certifiedAccountMapper;

    @Resource
    private CertifiedInfoMapper certifiedInfoMapper;

    @Resource
    private RedisUtil redisUtil;

    @Override
    public CertifiedAccountDto login(LoginParam param, HttpServletResponse response) throws Exception {
        //是否能够进行登录操作
        if(redisUtil.exists(RedisKeyUtil.cannotLogin(param.getCertifiedAccountAccount()))){
            throw new CertifiedException(CertifiedExceptionCode.CANNOT_LOGIN);
        }
        //账号密码是否为空
        if(param.getCertifiedAccountAccount()==null||param.getCertifiedAccountPass()==null){
            throw new CertifiedException(CertifiedExceptionCode.INVALID_INPUT);
        }
        QueryWrapper<CertifiedAccount> wrapper = new QueryWrapper<CertifiedAccount>();
        wrapper.eq("certified_account_account",param.getCertifiedAccountAccount());
        CertifiedAccount certifiedAccount = certifiedAccountMapper.selectOne(wrapper);
        //账号是否存在
        if(certifiedAccount==null){
            throw new CertifiedException(CertifiedExceptionCode.ACCOUNT_INEXISTENCE);
        }
        //账号是否被禁用
        if(certifiedAccount.getCertifiedAccountState()==CertifiedCode.ACCOUNT_DISABLE.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.ACCOUNT_DISABLE);
        }
        //密码是否正确
        if(!certifiedAccount.getCertifiedAccountPass().equals(param.getCertifiedAccountPass())){
            //不正确就将错误次数加1
            if(redisUtil.exists(RedisKeyUtil.passWordError(param.getCertifiedAccountAccount()))){
                redisUtil.incr(RedisKeyUtil.passWordError(param.getCertifiedAccountAccount()));
            }else {
                redisUtil.set(RedisKeyUtil.passWordError(param.getCertifiedAccountAccount()),"1",60*5);
            }
            //如果次数等于大于5，则一小时内不允许登录
            String s = RedisKeyUtil.passWordError(param.getCertifiedAccountAccount());
            if (Integer.parseInt(redisUtil.get(s)) >= CertifiedCode.MAX_ERROR.getCode()){
                redisUtil.set(RedisKeyUtil.cannotLogin(param.getCertifiedAccountAccount()),"1",60*60);
            }
            throw new CertifiedException(CertifiedExceptionCode.PASS_ERROR);
        }
        //密码正确，生成token
        //键值对存值需要传递的参数
        HashMap<String, Object> body = new HashMap<String, Object>();
        //将id放入body
        body.put("id",certifiedAccount.getCertifiedAccountId());
        //所属物业id
        body.put("certifiedInfoId",certifiedAccount.getCertifiedInfoId());
        //角色
        body.put("accountRole",certifiedAccount.getAccountRole());
        //生成jwt字符串(需要传入数据体默认有效时间为15分钟)
        String shortToken = JwtUtil.createAdminToken(body);
        //设置token响应tou为jwt
        response.setHeader("token",shortToken);
        //在跨域请求访问时 必须公开该请求头 前端才能获取到
        response.setHeader("Access-Control-Expose-Headers","token");

        //生成长token,以短token为键长token为值存入redis,该键值对存在的时间与长token时间一致
        String longToken = JwtUtil.createToken(body,24 * 60);
        redisUtil.set(shortToken,longToken,60*60*24);

        CertifiedAccountDto dto = BeanUtil.toBean(certifiedAccount, CertifiedAccountDto.class);
        dto.setToken(shortToken);
        return dto;
    }

    @Override
    public CertifiedAccountDto RegisterAccount(RegisterParam param) {
        //账号是否重复
        QueryWrapper<CertifiedAccount> wrapper = new QueryWrapper<CertifiedAccount>();
        wrapper.eq("certified_account_account",param.getCertifiedAccountAccount());
        CertifiedAccount certifiedAccount = certifiedAccountMapper.selectOne(wrapper);
        if(certifiedAccount!=null){
            throw new CertifiedException(CertifiedExceptionCode.ACCOUNT_EXIST);
        }
        //新增
        CertifiedAccount certifiedAccount1 = new CertifiedAccount();
        certifiedAccount1.setAccountRole(CertifiedCode.GENERAL_ADMIN.getCode());//角色
        certifiedAccount1.setCertifiedAccountState(CertifiedCode.ACCOUNT_ENABLE.getCode());//状态
        certifiedAccount1.setCertifiedInfoId(Integer.valueOf(param.getCertifiedInfoId()));//所属物业id
        certifiedAccount1.setCertifiedAccountAccount(param.getCertifiedAccountAccount());//账号
        certifiedAccount1.setCertifiedAccountPass(param.getCertifiedAccountPass());//密码
        certifiedAccountMapper.insert(certifiedAccount1);
        CertifiedAccountDto dto = BeanUtil.toBean(certifiedAccount1, CertifiedAccountDto.class);
        return dto;
    }

    @Override
    public void bannedAccount(BannedAccountParam param) {
        //当前角色是否是超级管理员
        if(param.getAccountRole()!=CertifiedCode.SUPER_ADMIN.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.HAVE_NO_AUTHORITY);
        }
        //是否存在该被禁用管理员
        CertifiedAccount certifiedAccount = certifiedAccountMapper.selectById(param.getCertifiedAccountId());
        if(certifiedAccount==null){
            throw new CertifiedException(CertifiedExceptionCode.ACCOUNT_INEXISTENCE);
        }
        //该被禁用管理员是否是超级管理员
        if(certifiedAccount.getAccountRole()==CertifiedCode.SUPER_ADMIN.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.CANNOT_DISABLE);
        }
        //被禁用管理员是否已经被禁用
        if(certifiedAccount.getCertifiedAccountState()==CertifiedCode.ACCOUNT_DISABLE.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.DO_NOT_REPEAT_OPERATION);
        }
        //是否是同一个物业
        if(certifiedAccount.getCertifiedInfoId()!=param.getCertifiedInfoId()){
            throw new CertifiedException(CertifiedExceptionCode.CANNOT_OTHER_PROPERTIES);
        }
        //禁用管理员
        certifiedAccount.setCertifiedAccountState(CertifiedCode.ACCOUNT_DISABLE.getCode());
        certifiedAccountMapper.updateById(certifiedAccount);
    }

    @Override
    public void enableAccount(BannedAccountParam param) {
        //当前角色是否是超级管理员
        if(param.getAccountRole()!=CertifiedCode.SUPER_ADMIN.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.HAVE_NO_AUTHORITY);
        }
        //是否存在该被启用管理员
        CertifiedAccount certifiedAccount = certifiedAccountMapper.selectById(param.getCertifiedAccountId());
        if(certifiedAccount==null){
            throw new CertifiedException(CertifiedExceptionCode.ACCOUNT_INEXISTENCE);
        }
        //该启用管理员是否是超级管理员
        if(certifiedAccount.getAccountRole()==CertifiedCode.SUPER_ADMIN.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.CANNOT_DISABLE);
        }
        //被启用管理员是否已经被启用
        if(certifiedAccount.getCertifiedAccountState()==CertifiedCode.ACCOUNT_ENABLE.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.DO_NOT_REPEAT_OPERATION);
        }
        //是否是同一个物业
        if(certifiedAccount.getCertifiedInfoId()!=param.getCertifiedInfoId()){
            throw new CertifiedException(CertifiedExceptionCode.CANNOT_OTHER_PROPERTIES);
        }
        //启用管理员
        certifiedAccount.setCertifiedAccountState(CertifiedCode.ACCOUNT_ENABLE.getCode());
        certifiedAccountMapper.updateById(certifiedAccount);
    }

    @Override
    public void updatePassword(UpdatePasswordParam param) {
        //账号是否存在
        CertifiedAccount certifiedAccount = certifiedAccountMapper.selectById(param.getCertifiedAccountId());
        if(certifiedAccount==null){
            throw new CertifiedException(CertifiedExceptionCode.ACCOUNT_INEXISTENCE);
        }
        //旧密码是否正确
        if(!certifiedAccount.getCertifiedAccountPass().equals(param.getOldCertifiedAccountPass())){
            throw new CertifiedException(CertifiedExceptionCode.PASS_ERROR);
        }
        //修改密码
        certifiedAccount.setCertifiedAccountPass(param.getNewCertifiedAccountPass());
        certifiedAccountMapper.updateById(certifiedAccount);
    }

    @Override
    public void setSuperAdmin(String id, Integer accountId) {
        //判断登录的账号是否是超级管理员
        CertifiedAccount certifiedAccount = certifiedAccountMapper.selectById(id);
        if(certifiedAccount.getAccountRole()!= CertifiedCode.SUPER_ADMIN.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.HAVE_NO_AUTHORITY);
        }
        //判断操作的账号是否是超级管理员
        CertifiedAccount certifiedAccount1 = certifiedAccountMapper.selectById(accountId);
        if(certifiedAccount1 != null && certifiedAccount1.getAccountRole() == CertifiedCode.SUPER_ADMIN.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.DO_NOT_REPEAT_OPERATION);
        }
        //判断操作的账号是否与登录的账号同属一个物业
        if(certifiedAccount1.getCertifiedInfoId()!=certifiedAccount.getCertifiedInfoId()){
            throw new CertifiedException(CertifiedExceptionCode.HAVE_NO_AUTHORITY);
        }
        //修改账号为超级管理员
        certifiedAccount1.setAccountRole(CertifiedCode.SUPER_ADMIN.getCode());
        certifiedAccountMapper.updateById(certifiedAccount1);
    }

    @Override
    public void setNormalAdmin(String id, Integer accountId) {
        //不能设置自己
        if(Integer.valueOf(id) == accountId){
            throw new CertifiedException(CertifiedExceptionCode.CANNOT_OPERATE_ONESELF);
        }
        //判断登录的账号是否是超级管理员
        CertifiedAccount certifiedAccount = certifiedAccountMapper.selectById(id);
        if(certifiedAccount.getAccountRole()!= CertifiedCode.SUPER_ADMIN.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.HAVE_NO_AUTHORITY);
        }
        //判断操作的账号是否是普通管理员
        CertifiedAccount certifiedAccount1 = certifiedAccountMapper.selectById(accountId);
        if(certifiedAccount1 != null && certifiedAccount1.getAccountRole() == CertifiedCode.GENERAL_ADMIN.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.DO_NOT_REPEAT_OPERATION);
        }
        //判断操作的账号是否与登录的账号同属一个物业
        if(certifiedAccount1.getCertifiedInfoId()!=certifiedAccount.getCertifiedInfoId()){
            throw new CertifiedException(CertifiedExceptionCode.HAVE_NO_AUTHORITY);
        }
        //修改账号为普通管理员
        certifiedAccount1.setAccountRole(CertifiedCode.GENERAL_ADMIN.getCode());
        certifiedAccountMapper.updateById(certifiedAccount1);

    }

    @Override
    public CertifiedAccountInfoDto getAccountInformation(String id) {
        //当前账号是存在
        CertifiedAccount certifiedAccount = certifiedAccountMapper.selectById(id);
        if(certifiedAccount==null){
            throw new CertifiedException(CertifiedExceptionCode.ACCOUNT_INEXISTENCE);
        }
        CertifiedAccountInfoDto dto = new CertifiedAccountInfoDto();
        dto.setAccount(certifiedAccount.getCertifiedAccountAccount());
        if(certifiedAccount.getAccountRole()==0){
            dto.setRole("超级管理员");
        }else {
            dto.setRole("普通管理员");
        }
        CertifiedInfo certifiedInfo = certifiedInfoMapper.selectById(certifiedAccount.getCertifiedInfoId());
        dto.setCertifiedName(certifiedInfo.getCertifiedInfoName());
        dto.setCertifiedInfoId(certifiedInfo.getCertifiedInfoId());
        return dto;
    }

    @Override
    public PageInfo<CertifiedAccountInfoDto> loadAllAccount(LoadAllAccountParam param, String id) {
        Page<CertifiedAccount> page = new Page<>(param.getPageNum() == null ? 1 : param.getPageNum(), param.getPageSize() == null ? 5 : param.getPageSize());
        //查询的是不是自己的物业公司
        CertifiedAccount certifiedAccount = certifiedAccountMapper.selectById(id);
        if (certifiedAccount.getCertifiedInfoId()!=param.getCertifiedInfoId()){
            throw new CertifiedException(CertifiedExceptionCode.CANNOT_OTHER_PROPERTIES);
        }
        //查询自己的物业公司账号
        QueryWrapper<CertifiedAccount> wrapper = new QueryWrapper<>();
        wrapper.eq("certified_info_id",certifiedAccount.getCertifiedInfoId());
        wrapper.orderByDesc("certified_account_id");
        certifiedAccountMapper.selectPage(page, wrapper);
        PageInfo pageInfo = BeanUtil.toBean(page, PageInfo.class);
        pageInfo.setList(page.getRecords());
        pageInfo.setPages(page.getPages());
        return pageInfo;
    }

    @Override
    public void certifiedAccountService(DeleteAccountParam param) {
        //操作账号是否是超级管理员
        if(param.getAccountRole()!=CertifiedCode.SUPER_ADMIN.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.HAVE_NO_AUTHORITY);
        }
        //被操作账号是否存在,是否是超级管理员
        CertifiedAccount certifiedAccount = certifiedAccountMapper.selectById(param.getCertifiedAccountId());
        if(certifiedAccount==null){
            throw new CertifiedException(CertifiedExceptionCode.ACCOUNT_INEXISTENCE);
        }
        if(certifiedAccount.getAccountRole()==CertifiedCode.SUPER_ADMIN.getCode()){
            throw new CertifiedException(CertifiedExceptionCode.CANNOT_DISABLE);
        }
        certifiedAccountMapper.deleteById(param.getCertifiedAccountId());
    }

    @Override
    public CertifiedAccount updatecertifiedstate(String id) {
        QueryWrapper<CertifiedAccount> wrapper = new QueryWrapper<>();
        wrapper.eq("certified_account_id", id);
        CertifiedAccount certifiedAccount = certifiedAccountMapper.selectOne(wrapper);
        if (certifiedAccount != null) {
            Integer certifiedAccountState = certifiedAccount.getCertifiedAccountState();
            if (certifiedAccountState == 0) {
                certifiedAccount.setCertifiedAccountState(1);
            } else {
                certifiedAccount.setCertifiedAccountState(0);
            }
            certifiedAccountMapper.updateById(certifiedAccount);
        }
        return certifiedAccount;
    }
}
